/*
 * Questionnaire.java
 *
 * Defines a simple questionnaire game for users to provide feedback on their
 * experience.
 */

package game;

import main.CSVReader;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.MemoryImageSource;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import javax.swing.Timer;

/**
 * Defines a simple questionnaire game for users to provide feedback on their
 * experience. The format should be similar to that of the quizzes, but users
 * don't get told they got a right or wrong answer, nor do they get money for
 * their answers.
 * 
 * @author Justin
 */
public class Questionnaire extends Game {
    /** The amount of time, in seconds, available for the game. */
    final int GAME_TIME = 180;

    /** The file that holds the questionnaire data in CSV format. */
    private String dataFile = "";

    // CSV constants.
    final int CSV_QUESTION = 0;
    final int CSV_ANSWERA = 1;
    final int CSV_ANSWERB = 2;
	final int CSV_CORRECT = 3;

	/** How much the subject earns for getting a correct answer ($). */
	double correctPay;

	/** How much the subject earns from the quiz this session. */
	double sessionAmountWon;

    /** Timer for the game countdown. */
    Timer timer = new Timer (1000, new TimeListener());

    /** Array for questionnaire questions. */
    ArrayList<String> questions = new ArrayList<String>();

    /** Array for questionnaire answer 'A's. */
    ArrayList<String> answerAs = new ArrayList<String>();

    /** Array for questionnaire answer 'B's. */
    ArrayList<String> answerBs = new ArrayList<String>();

	/** Array for questionnaire correct answers. */
	ArrayList<String> correctAnswers = new ArrayList<String>();

    /** Index in the questions array; what question we're on. */
    int currentQuestion;

	/** Amount of time, in seconds, the subject spent making their decision. */
	int playerThinkTime = 0;

	// End game constants.
	final int EG_NORMAL = 0;
	final int EG_BADFILE = 1;
	final int EG_TIMEOUT = 2;
	final int EG_ANS_A = 1;
	final int EG_ANS_B = 2;
	final int EG_CORRECT = 1;
	final int EG_WRONG = 2;
	final int EG_OPINION = 3;

    // METHODS -----------------------------------------------------------------
    /**
     * Constructor for the Questionnaire game.
     */
    public Questionnaire (String params, int currentRep) {
        super();
        initComponents();
        this.setVisible (true);
        hideMouse();

		sessionAmountWon = 0;
        secs = GAME_TIME;
        timer.start();
        updateTimerLabel();

		String paramPart[] = params.split (",");
		dataFile = paramPart[2];
		correctPay = Double.parseDouble(paramPart[3]);
		this.params = params;
		repTot = Integer.parseInt (paramPart[1]);
		repNum = currentRep;

        getData();
        currentQuestion = 0;
        displayQuestion (currentQuestion);

        runner.addMouseListener (new Questionnaire.CheckMouse());
        this.addMouseListener (new Questionnaire.CheckMouse());
		this.getGlassPane().addMouseListener(new Questionnaire.CheckMouse());
    }

    // GAME --------------------------------------------------------------------
    /**
     * Updates the layout to display the given question.
     * @param currentQuestion
     *          The index in the questions array we want to display.
     */
    private void displayQuestion (int currentQuestion) {
        if (currentQuestion >= questions.size())
			return;
		
		questionLabel.setText ("<html><p>" + questions.get(currentQuestion)
                + "</p>");
        String answersText = "<html><p>A: ";
        answersText += answerAs.get(currentQuestion) + "</p><p>B: ";
        answersText += answerBs.get(currentQuestion) + "</b></html>";
        choicesLabel.setText (answersText);
    }

    /**
     * Ends the game, writes to log file.
     */
    private void endGame (int status) {
		String payment = "";
		String oppPay = "";
		
		if (status == EG_NORMAL)
			payment = String.format("$%.2f", sessionAmountWon);
		else if (status == EG_BADFILE) {
			payment = "BadFile";
			oppPay = "BadFile";
		}
		else if (status == EG_TIMEOUT) {
			payment = "TimeOut";
			oppPay = "TimeOut";
		}

		writeLog (playerId + ",,\"" + params + "\"," + repNum + "," + repTot
			+ "," + payment + "," + oppPay);
		setVisible(false);
		free=true;
    }

    // LAYOUT ------------------------------------------------------------------
    /**
     * Gets the questions and possible answers from the data file.
     */
    private void getData() {
        try {
            CSVReader reader = new CSVReader (new FileReader
                    (new File ("questionnaire/" + dataFile)));
            ArrayList<ArrayList<String>> quizData =
                    (ArrayList<ArrayList<String>>) reader.readAll();

			if (quizData.size() < 2) {
				System.err.println ("[ERROR]: Questionnaire file has no" +
						" questions (" + dataFile + ").");
				endGame (EG_BADFILE);
			}

            // Start at one to ignore the labels at top.
            for (int i=1; i<quizData.size(); i++) {
                questions.add (quizData.get(i).get(CSV_QUESTION).trim());
                answerAs.add (quizData.get(i).get(CSV_ANSWERA).trim());
                answerBs.add (quizData.get(i).get(CSV_ANSWERB).trim());
				correctAnswers.add (quizData.get(i).get(CSV_CORRECT).trim());
            }
        }
        catch (Exception e) {
            System.err.println ("[ERROR]: Error while trying to open the "
					+ "questionnaire data file (" + dataFile + ").");
            e.printStackTrace();
        }
    }

    /**
     * Based on the time remaining, updates the time remaining label.
     */
    private void updateTimerLabel() {
        int min = secs / 60;
        int sec = secs % 60;
        timeLabel.setText (min + ":" + ((sec < 10) ? "0" : "") + sec);
    }
    
    /**
     * Hides the mouse so the user can't see it.
     */
    private void hideMouse() {
        int[] pixels = new int[16 * 16];
        Image image = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(16, 16, pixels, 0, 16));
        Cursor transparentCursor = Toolkit.getDefaultToolkit().createCustomCursor(image, new Point(0, 0), "invisibleCursor");
        this.getGlassPane().setCursor(transparentCursor);
		this.getGlassPane().setVisible(true);
        runner.setCursor(transparentCursor);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        timeLabel = new javax.swing.JLabel();
        titleLabel = new javax.swing.JLabel();
        questionLabel = new javax.swing.JLabel();
        lblYes = new javax.swing.JLabel();
        lblNo = new javax.swing.JLabel();
        choicesLabel = new javax.swing.JLabel();

        setBackground(new java.awt.Color(255, 255, 255));
        setBorder(null);
        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setMaximumSize(new java.awt.Dimension(800, 600));
        setMinimumSize(new java.awt.Dimension(800, 600));
        setPreferredSize(new java.awt.Dimension(800, 600));

        timeLabel.setFont(new java.awt.Font("Calibri", 1, 36));
        timeLabel.setForeground(new java.awt.Color(153, 102, 0));
        timeLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/hrGlass.png"))); // NOI18N
        timeLabel.setText("3:00");

        titleLabel.setFont(new java.awt.Font("Calibri", 1, 28));
        titleLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        titleLabel.setText("Questionnaire");

        questionLabel.setFont(new java.awt.Font("Calibri", 1, 26));
        questionLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        questionLabel.setText("Question 1");

        lblYes.setFont(new java.awt.Font("Calibri", 1, 24));
        lblYes.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        lblYes.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/redA.png"))); // NOI18N

        lblNo.setFont(new java.awt.Font("Calibri", 1, 24));
        lblNo.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        lblNo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/greenB.png"))); // NOI18N

        choicesLabel.setFont(new java.awt.Font("Calibri", 1, 26)); // NOI18N
        choicesLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        choicesLabel.setText("<html>\nA: Answer 1<br>\nB: Answer 2\n</html>");
        choicesLabel.setMaximumSize(new java.awt.Dimension(129, 66));
        choicesLabel.setMinimumSize(new java.awt.Dimension(129, 66));

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(timeLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE)
                    .add(titleLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE))
                .addContainerGap())
            .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                .add(121, 121, 121)
                .add(lblYes, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 233, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 119, Short.MAX_VALUE)
                .add(lblNo)
                .add(94, 94, 94))
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(choicesLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE)
                .addContainerGap())
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(questionLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(timeLabel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 48, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(titleLabel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 27, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(18, 18, 18)
                .add(questionLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 95, Short.MAX_VALUE)
                .add(18, 18, 18)
                .add(choicesLabel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 229, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(18, 18, 18)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(lblYes)
                    .add(lblNo))
                .add(66, 66, 66))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        /*try {
            JFrame main = new JFrame();
            JDesktopPane dPane = new JDesktopPane();
            Questionnaire frame = new Questionnaire();
            main.setSize(820, 620);
            dPane.add(frame);
            main.add(dPane);
            main.setVisible(true);
            dPane.setVisible(true);
            frame.setSelected(true);
            frame.setVisible(true);
        }
        catch(Exception ex) {
            ex.printStackTrace();
        }*/
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel choicesLabel;
    private javax.swing.JLabel lblNo;
    private javax.swing.JLabel lblYes;
    private javax.swing.JLabel questionLabel;
    private javax.swing.JLabel timeLabel;
    private javax.swing.JLabel titleLabel;
    // End of variables declaration//GEN-END:variables

    /**
     * Defines what we do when the user clicks the mouse.
     */
    class CheckMouse implements MouseListener{
        public void mousePressed (MouseEvent e) { hideMouse(); }
        public void mouseReleased (MouseEvent e) {}
        public void mouseEntered (MouseEvent e) {}
        public void mouseExited (MouseEvent e) {}
        
        /**
         * Handle mouse clicks.
         * 
         * @param e The MouseEvent.
         */
        
       public void mouseClicked (MouseEvent e){
            int modifiers = e.getModifiers();
			boolean unpaidAnswer = true;
			boolean endGame = true;

			if (currentQuestion < questions.size()) {
				endGame = false;
				unpaidAnswer = (
					!correctAnswers.get(currentQuestion).toLowerCase().equals("a")
				 && !correctAnswers.get(currentQuestion).toLowerCase().equals("b"));

				// Left click.
				if ((modifiers & InputEvent.BUTTON1_MASK) ==
						InputEvent.BUTTON1_MASK) {
					boolean correct = (correctAnswers.get(currentQuestion)
								.toLowerCase().equals("a"));
					int status;

					if (correct) {
						totalMoneyWon += correctPay;
						sessionAmountWon += correctPay;
						status = EG_CORRECT;
					}
					else
						status = EG_WRONG;
					if (unpaidAnswer)
						status = EG_OPINION;

					writeGameLog(playerId + "," + playerThinkTime + ","
						+ dataFile + "," + (currentQuestion+1) + "," + EG_ANS_A
						+ "," + status);
					playerThinkTime = 0;

					currentQuestion++;
					if (currentQuestion < questions.size())
						displayQuestion (currentQuestion);
					else
						endGame = true;
				}

				// Right click.
				else if ((modifiers & InputEvent.BUTTON3_MASK) ==
						InputEvent.BUTTON3_MASK) {
					boolean correct = (correctAnswers.get(currentQuestion)
								.toLowerCase().equals("b"));
					int status;

					if (correct) {
						totalMoneyWon += correctPay;
						sessionAmountWon += correctPay;
						status = EG_CORRECT;
					}
					else
						status = EG_WRONG;
					if (unpaidAnswer)
						status = EG_OPINION;
					
					writeGameLog(playerId + "," + playerThinkTime + ","
						+ dataFile + "," + (currentQuestion+1) + "," + EG_ANS_B
						+ "," + status);
					playerThinkTime = 0;

					currentQuestion++;
					if (currentQuestion < questions.size())
						displayQuestion (currentQuestion);
					else
						endGame = true;
				}

				// Invalid input.
				else {
					// Do nothing.
				}
			}
			if (endGame) {
				endGame (EG_NORMAL);
			}
        }
    }

    /**
     * Handles timer actions.
     */
    class TimeListener implements ActionListener {
    	/**
         * Decrement the time remaining, if there is any. If the user has run
         * out of time, then exit.
         *
         * @param e The ActionEvent.
         */
        
        public void actionPerformed(ActionEvent e) {
            if (secs > 0) {
                secs--;
				playerThinkTime++;
                updateTimerLabel();
            }
            else {
                timer.stop();
                questionLabel.setText ("Sorry, your time is up.");
                endGame (EG_TIMEOUT);
            }
    	}
    }
}
